package com.example.demo.shiro.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.Iterator;

/**
 * 加入 httpMethod 支持
 *
 * @author zhaiding
 * @since 2020-01-08
 */
@Slf4j
public class RestPathMatchingFilterChainResolver extends PathMatchingFilterChainResolver {

    private static final String JOINT = "==";

    @Override
    public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {

        FilterChainManager filterChainManager = this.getFilterChainManager();
        if (!filterChainManager.hasChains()) {
            return null;
        } else {
            String requestURI = this.getPathWithinApplication(request);
            Iterator<String> chainNames = filterChainManager.getChainNames().iterator();

            String pathPattern;
            boolean flag;
            String[] strings;
            do {
                if (!chainNames.hasNext()) {
                    return null;
                }
                pathPattern = chainNames.next();
                strings = pathPattern.split(JOINT);
                if (strings.length == 2) {
                    // 分割出url+httpMethod,判断httpMethod和request请求的method是否一致,不一致直接false
                    flag = !WebUtils.toHttp(request).getMethod().toUpperCase().equals(strings[1].toUpperCase());
                } else {
                    flag = false;
                }
                pathPattern = strings[0];
            } while (!this.pathMatches(pathPattern, requestURI) || flag);

            if (log.isTraceEnabled()) {
                log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "].  Utilizing corresponding filter chain...");
            }
            if (strings.length == 2) {
                pathPattern = pathPattern.concat(JOINT).concat(WebUtils.toHttp(request).getMethod().toUpperCase());
            }
            return filterChainManager.proxy(originalChain, pathPattern);
        }
    }
}
